import CryptoJS from 'crypto-js'

// AES加密模式（仅支持CBC，因为crypto-js不支持真正的GCM）
export type AESMode = 'CBC'

// AES加密结果
export interface AESResult {
  encrypted: string
  iv: string
}

/**
 * AES加密
 * @param plaintext 明文
 * @param key 密钥（hex格式）
 * @param mode 加密模式
 * @param iv 初始向量（可选）
 */
export const AESEncrypt = (
  plaintext: string,
  key: string,
  mode: AESMode = 'CBC',
  iv?: string
): AESResult => {
  try {
    const keyWords = CryptoJS.enc.Hex.parse(key)
    const ivWords = iv ? CryptoJS.enc.Hex.parse(iv) : CryptoJS.lib.WordArray.random(16)

    // 使用CBC模式进行加密
    const cipher = CryptoJS.AES.encrypt(plaintext, keyWords, {
      iv: ivWords,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    })

    return {
      encrypted: cipher.ciphertext.toString(CryptoJS.enc.Base64),
      iv: ivWords.toString(CryptoJS.enc.Hex)
    }

  } catch (error) {
    throw new Error(`AES加密失败: ${error}`)
  }
}

/**
 * AES解密
 * @param encryptedData 加密数据（base64格式）
 * @param key 密钥（hex格式）
 * @param mode 加密模式
 * @param iv 初始向量（hex格式）
 */
export const AESDecrypt = (
  encryptedData: string,
  key: string,
  mode: AESMode = 'CBC',
  iv?: string
): string => {
  try {
    if (!iv) {
      throw new Error('缺少初始向量')
    }

    const keyWords = CryptoJS.enc.Hex.parse(key)
    const ivWords = CryptoJS.enc.Hex.parse(iv)
    const encryptedWords = CryptoJS.enc.Base64.parse(encryptedData)

    // 使用CBC模式进行解密
    const cipherParams = CryptoJS.lib.CipherParams.create({
      ciphertext: encryptedWords
    })

    const decrypted = CryptoJS.AES.decrypt(cipherParams, keyWords, {
      iv: ivWords,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    })

    const result = decrypted.toString(CryptoJS.enc.Utf8)

    if (!result) {
      throw new Error('解密失败，可能密钥错误')
    }

    return result

  } catch (error) {
    throw new Error(`AES解密失败: ${error}`)
  }
}

/**
 * 生成AES密钥
 * @param bits 密钥长度（128, 192, 256）
 */
export const generateAESKey = (bits: 128 | 192 | 256 = 256): string => {
  const bytes = bits / 8
  return CryptoJS.lib.WordArray.random(bytes).toString(CryptoJS.enc.Hex)
}

/**
 * 生成随机IV
 */
export const generateIV = (): string => {
  return CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Hex)
}